﻿using EmbeddedSharp.Core;
using EmbeddedSharp.Scripting.Function;
using EmbeddedSharp.Scripting.Function.Context;
using EmbeddedSharp.Scripting.Function.Flow;

namespace EmbeddedSharp.Scripting
{
    public class ContextExpressionParser : ExpressionParser
    {
        public ContextExpressionParser(Lexer lexer, IContext context)
            : base(lexer)
        {
            Context = context;
        }

        public ContextExpressionParser(string expr, IContext context)
            : base(expr)
        {
            Context = context;
        }

        public IContext Context { get; set; }

        protected override Node CreateAssignNode()
        {
            return new AssignNode(Context);
        }

        protected override Node CreateDeclareNode()
        {
            return new DeclareNode();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public override Node GetVariableNode(string value)
        {
            if (value.ToLower().Equals("true")
                || value.ToLower().Equals("false"))
            {
                return new IdentifierNode(value);
            }
            if (value.ToLower().Equals("nil"))
            {
                return new NilNode();
            }

            return new VariableNode(value) { Context = Context };
        }

        /// <summary>
        /// Return a reference
        /// </summary>
        /// <param name="p"></param>
        protected override FuncNode CannotFindSuitableFunction(string p)
        {
            var refNode = new FunctionReferenceNode(p) { Context = Context };

            return refNode;
        }

        protected override void Parse(Token token)
        {
            switch (token.TokenType)
            {
                case TokenType.LeftBracket:
                    var pcb = new ParameterCountStruct
                                   {
                                       numberOfParameters = 0,
                                       parethesisDepth = currentParethesisDepth + 1
                                   };

                    var bn = new BlockNode(Context);
                    operatorStack.Push(bn);
                    currentParethesisDepth++;

                    ParameterCountStack.Push(pcb);
                    operatorStack.Push(new EmbraceNode());
                    Parse();
                    //stack.Push(root);
                    break;
                default:
                    return;
            }
        }
    }
}